package com.dbflow5.sql.language;

import com.dbflow5.BaseUnitTest;
import com.dbflow5.models.SimpleModel_Table;
import com.dbflow5.models.SimpleTestModels;
import com.dbflow5.models.TwoColumnModel_Table;
import com.dbflow5.query.From;
import com.dbflow5.query.Operator;
import com.dbflow5.query.SQLite;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class JoinTest extends BaseUnitTest {
    @Test
    public void validateAliasJoin() {
        assertEquals("SELECT * FROM SimpleModel INNER JOIN TwoColumnModel AS Name ON TwoColumnModel.name=name",
            ((SQLite.select().from(SimpleTestModels.SimpleModel.class).innerJoin(SimpleTestModels.TwoColumnModel.class).as("Name").on(TwoColumnModel_Table.name.withTable().eq(SimpleModel_Table.name)).getQuery().trim())));
    }

    @Test
    public void testInnerJoin() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).innerJoin(SimpleTestModels.TwoColumnModel.class).on(TwoColumnModel_Table.name.withTable().eq(SimpleModel_Table.name));
        assertEquals("SELECT * FROM SimpleModel INNER JOIN TwoColumnModel ON TwoColumnModel.name=name",
            join.getQuery().trim());
    }

    @Test
    public void testLeftOuterJoin() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).leftOuterJoin(SimpleTestModels.TwoColumnModel.class).on(TwoColumnModel_Table.name.withTable().eq(SimpleModel_Table.name));
        assertEquals("SELECT * FROM SimpleModel LEFT OUTER JOIN TwoColumnModel ON TwoColumnModel.name=name",
            join.getQuery().trim());
    }

    @Test
    public void testCrossJoin() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).crossJoin(SimpleTestModels.TwoColumnModel.class).on(TwoColumnModel_Table.name.withTable().eq(SimpleModel_Table.name));
        assertEquals("SELECT * FROM SimpleModel CROSS JOIN TwoColumnModel ON TwoColumnModel.name=name",
            join.getQuery().trim());
    }

    @Test
    public void testMultiJoin() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).innerJoin(SimpleTestModels.TwoColumnModel.class).on(TwoColumnModel_Table.name.withTable().eq(SimpleModel_Table.name)).crossJoin(SimpleTestModels.TwoColumnModel.class)
            .on(TwoColumnModel_Table.id.withTable().eq(SimpleModel_Table.name));
        assertEquals("SELECT * FROM SimpleModel INNER JOIN TwoColumnModel ON TwoColumnModel.name=name" +
                " CROSS JOIN TwoColumnModel ON TwoColumnModel.id=name",
            join.getQuery().trim());
    }

    @Test
    public void testInnerJoinOnUsing() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).innerJoin(SimpleTestModels.TwoColumnModel.class).using(SimpleModel_Table.name.withTable());
        assertEquals("SELECT * FROM SimpleModel INNER JOIN TwoColumnModel USING (SimpleModel.name)",
            join.getQuery().trim());
    }

    @Test
    public void testNaturalJoin() {
        From<SimpleTestModels.SimpleModel> join = SQLite.select().from(SimpleTestModels.SimpleModel.class).naturalJoin(SimpleTestModels.TwoColumnModel.class).end();
        assertEquals("SELECT * FROM SimpleModel NATURAL JOIN TwoColumnModel",
            join.getQuery().trim());
    }
}
